#pragma once

#include <iostream>
#include <queue>
#include <pthread.h>

template <class T>
class BlockQueue
{
    static const int defalutnum = 5;
public:
    BlockQueue(int maxcap = defalutnum) : maxcap_(maxcap)
    {
        pthread_mutex_init(&mutex_,nullptr);
        pthread_cond_init(&p_cond_,nullptr);
        pthread_cond_init(&c_cond_,nullptr);
        low_water_ = maxcap_ / 3;
        high_water_ = (maxcap_ * 2) / 3; 
    }

    T pop()
    {
        pthread_mutex_lock(&mutex_);
        while (q_.size() == 0)
        {
            pthread_cond_wait(&c_cond_,&mutex_);
        }

        T out = q_.front();
        q_.pop();   //1. 调用的时候, 自动释放锁 2. 因为唤醒而返回的时候会重新竞争锁,才会向下执行

        //if (q_.size() < low_water_)
        pthread_cond_signal(&p_cond_);
        pthread_mutex_unlock(&mutex_);

        return out;

       
    }

    void push(const T& in)
    {
        pthread_mutex_lock(&mutex_);

        while (q_.size() == maxcap_)
        {
            //std::cout << "in : q_.size() " << q_.size() << std::endl;
            pthread_cond_wait(&p_cond_,&mutex_);  //调用的时候会自己释放锁
        }
        q_.push(in);

        //if (q_.size() > high_water_) pthread_cond_signal(&c_cond_);

        //std::cout << "out : q_.size() " << q_.size() << std::endl;
        pthread_cond_signal(&c_cond_);
        pthread_mutex_unlock(&mutex_);
    }

    ~BlockQueue()
    {
        pthread_mutex_destroy(&mutex_);
        pthread_cond_destroy(&p_cond_);
        pthread_cond_destroy(&c_cond_);
    }

private:
    std::queue<T> q_;     //共享资源
    //int mincap_
    int maxcap_;        //极值
    pthread_mutex_t mutex_;
    pthread_cond_t p_cond_;
    pthread_cond_t c_cond_;

    int low_water_ = 0;
    int high_water_ = 0;
};